package com.cats.template.sys.aggservices.impl;

import com.cats.template.sys.aggservices.SysAggService;
import com.cats.template.sys.enums.ResponseEnum;
import com.cats.template.sys.exception.FindException;
import com.cats.template.sys.exception.SqlException;
import com.cats.template.sys.pojo.dto.PermissionDto;
import com.cats.template.sys.pojo.dto.RoleDto;
import com.cats.template.sys.pojo.dto.UserDto;
import com.cats.template.sys.pojo.model.PermissionModel;
import com.cats.template.sys.pojo.model.RoleModel;
import com.cats.template.sys.pojo.model.UserModel;
import com.cats.template.sys.services.PermissionService;
import com.cats.template.sys.services.RoleService;
import com.cats.template.sys.services.UserService;
import com.cats.template.sys.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author duxiaobo
 * @date 2021/9/102:45 下午
 */
@Service
@Slf4j
public class SysAggServiceImpl implements SysAggService {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;

    @Override
    public UserDto getUserAndRolesByUserName(String userName) {
        UserModel userModel = userService.getUser(userName);
        if (Objects.isNull(userModel)) {
            throw new FindException(ResponseEnum.USER_NOT_EXIST_ERROR);
        }
        UserDto userDto = userModel.parseDto(UserDto.class);
        Set<RoleDto> roles = getRolesByUserId(userDto.getId());
        if (!CollectionUtils.isEmpty(roles)) {
            roles.forEach(role -> {
                Set<PermissionDto> permissionDtoSet = getPermissionDtoSetByRoleId(role.getId());
                role.setPermissions(permissionDtoSet);
            });
            userDto.setRoles(roles);
        }
        return userDto;
    }

    @Override
    public UserDto getUser(String userName) {
        UserModel user = userService.getUser(userName);
        return Objects.isNull(user) ? null : user.parseDto(UserDto.class);
    }

    @Override
    public UserDto getUser(Long userId) {
        UserModel user = userService.getById(userId);
        return Objects.isNull(user) ? null : user.parseDto(UserDto.class);
    }

    @Override
    public UserDto getUser(String userName, String password) {
        UserModel user = userService.getUser(userName, password);
        return Objects.isNull(user) ? null : user.parseDto(UserDto.class);
    }

    @Override
    public Set<RoleDto> getRolesByUserId(Long userId) {
        Set<RoleModel> roles = roleService.getRoleListByUserId(userId);
        return CollectionUtils.isEmpty(roles) ? Collections.emptySet() : roles.stream().map(role -> role.parseDto(RoleDto.class)).collect(Collectors.toSet());
    }

    @Override
    public Set<PermissionDto> getPermissionDtoSetByRoleId(Long roleId) {
        Set<PermissionModel> permissions = permissionService.getPermissionsByRoleId(roleId);
        return CollectionUtils.isEmpty(permissions) ? Collections.emptySet() : permissions.stream().map(permission -> permission.parseDto(PermissionDto.class)).collect(Collectors.toSet());
    }

    @Override
    public Set<PermissionDto> getPermissionDtoSetByUserId(Long userId) {
        Set<RoleDto> roles = getRolesByUserId(userId);
        Set<PermissionDto> permissionDtoSet = new HashSet<>();
        roles.forEach(role -> permissionDtoSet.addAll(getPermissionDtoSetByRoleId(role.getId())));
        return permissionDtoSet;
    }


    @Override
    public UserDto saveUser(UserDto userDto) {
        if (Objects.isNull(userDto.getId())){
            userDto.setSalt(userDto.getIdNumber().substring(14));
            userDto.setPassword(JwtUtils.encryptPassword("123456",userDto.getSalt()));
        }
        UserModel userModel = userDto.parseModel(UserModel.class);
        boolean flag = userService.saveOrUpdate(userModel);
        if (!flag) {
            throw new SqlException();
        }
        userDto.setId(userModel.getId());
        return userDto;
    }

    @Override
    public RoleDto saveRole(RoleDto roleDto) {
        RoleModel roleModel = roleDto.parseModel(RoleModel.class);
        boolean flag = roleService.saveOrUpdate(roleModel);
        if (!flag) {
            throw new SqlException();
        }
        roleDto.setId(roleModel.getId());
        return roleDto;
    }

    @Override
    public Set<RoleDto> saveRole(Set<RoleDto> roleDtoSet) {
        roleDtoSet.forEach(this::saveRole);
        return roleDtoSet;
    }

    @Override
    public PermissionDto savePermission(PermissionDto permissionDto) {
        PermissionModel permissionModel = permissionDto.parseModel(PermissionModel.class);
        boolean flag = permissionService.saveOrUpdate(permissionModel);
        if (!flag) {
            throw new SqlException();
        }
        permissionDto.setId(permissionModel.getId());
        return permissionDto;
    }

    @Override
    public Set<PermissionDto> savePermission(Set<PermissionDto> permissionDtoSet) {
        permissionDtoSet.forEach(this::savePermission);
        return permissionDtoSet;
    }

    @Override
    public RoleDto getRole(Long roleId) {
        RoleModel role = roleService.getById(roleId);
        return Objects.isNull(role) ? null : role.parseDto(RoleDto.class);
    }

    @Override
    public Boolean configRoles(Long userId, Set<Long> roleIds) {
        return userService.configRoles(userId, roleIds);
    }

    @Override
    public Boolean configPermissions(Long roleId, Set<Long> permissionIds) {
        return roleService.configPermissions(roleId, permissionIds);
    }

}
